﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Payroll.Common.Utils;
using Payroll.BusinessLogic.Caching;
using Payroll.BusinessLogic.Data;
using Payroll.Common;
using System.Web;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;

namespace Payroll.BusinessLogic.CustomerManager
{
    public partial class CustomerService : ICustomerService
    {
        #region Fields

        /// <summary>
        /// Object context
        /// </summary>
        private readonly PayrollHRDataContext m_context;

        /// <summary>
        /// Cache manager
        /// </summary>
        private readonly ICacheManager _cacheManager;
        /// <summary>
        /// Gets the local image path
        /// </summary>
        public string LocalImagePath
        {
            get
            {
                string path = HttpContext.Current.Request.PhysicalApplicationPath + "images\\Customer";
                return path;
            }
        }
        /// <summary>
        /// Gets a local thumb image path
        /// </summary>
        public string LocalThumbImagePath
        {
            get
            {
                string path = HttpContext.Current.Request.PhysicalApplicationPath + "images\\thumbs";
                return path;
            }
        }
        /// <summary>
        /// Gets an image quality
        /// </summary>
        public long ImageQuality
        {
            get
            {
                return 100L;
            }
        }
        private int LocalPicel
        {
            get { return 189; }
        }
        #endregion

        #region Ctor

        /// <summary>
        /// Ctor
        /// </summary>
        /// <param name="context">Object context</param>
        public CustomerService(PayrollHRDataContext context)
        {
            this.m_context = context;
            this._cacheManager = new PayrollRequestCache();
        }

        #endregion
        #region Methods
        public int Save(Customer c)
        {
            var item = (from cust in m_context.Customers
                        where cust.CustomerId == c.CustomerId
                        select cust).FirstOrDefault();

            bool flag = true;
            if (!CommonHelper.IsNull(item))
            {
                flag = false;
            }

            while (flag)
            {
            Search:
                var query = (from ce in m_context.Customers
                             where ce.CustomerId == c.CustType 
                             select ce).FirstOrDefault();
                if (CommonHelper.IsNull(query))
                {
                    flag = false;
                }
                else
                {
                    this.UpdateCustomerLastId(c.CustomerId);
                    goto Search;
                }
            }
            c.CustName = c.CustName.ToUpper();

            if (CommonHelper.IsNull(item))
            {
                item = new BusinessLogic.Data.Customer
                                                       {

                                                           #region Assign
                                                           CustName = c.CustName,
                                                           CustAddress = c.CustAddress,
                                                           CustContact = c.CustContact,
                                                           CustTaxCode = c.CustTaxCode,
                                                           CustEmail = c.CustEmail,
                                                           CustMobile = c.CustMobile,
                                                           CustPhoneNumber = c.CustPhoneNumber,
                                                           CustType = c.CustType,
                                                           Createby = c.Createby,
                                                           Modified = c.Modified,
                                                           CreateDate = c.CreateDate,
                                                           ModifiedDate = c.ModifiedDate,
                                                           CustCode = c.CustCode,
                                                           IsActive = true

                                                           #endregion
                                                       };
                m_context.Customers.InsertOnSubmit(item);
                this.UpdateCustomerLastId(c.CustomerId);
            }
            else
            {
                #region CustomerInfo
                item.CustName = c.CustName;
                item.CustAddress = c.CustAddress;
                item.CustContact = c.CustContact;
                item.CustTaxCode = c.CustTaxCode;
                item.CustEmail = c.CustEmail;
                item.CustMobile = c.CustMobile;
                item.CustPhoneNumber = c.CustPhoneNumber;
                item.CustType = c.CustType;
                item.Createby = c.Createby;
                item.Modified = c.Modified;
                item.CreateDate = c.CreateDate;
                item.ModifiedDate = c.ModifiedDate;
                item.CustCode = c.CustCode;
                #endregion
            }
            m_context.SubmitChanges();

            return item.CustomerId;
        }
        public void dong()
        {
            m_context.Dispose();
        }
        public int Delete(List<int> List)
        {
            foreach (var item in List)
            {
                var cust = (from c in m_context.Customers
                            where c.CustomerId == item
                            select c).FirstOrDefault();
                if (!CommonHelper.IsNull(item))
                {
                    cust.IsActive = false;
                    m_context.SubmitChanges();
                }
            }
            return 0;
        }

        public PagedList<Customer> GetAllCustomer(int pageSize, int pageIndex)
        {
            var query = from c in m_context.Customers where c.IsActive==true
                        orderby c.CustomerId descending
                        select new Customer
                        {
                            #region
                            CustomerId = c.CustomerId,
                            CustName = c.CustName,
                            CustAddress = c.CustAddress,
                            CustContact = c.CustContact,
                            CustTaxCode = c.CustTaxCode,
                            CustEmail = c.CustEmail,
                            CustMobile = c.CustMobile,
                            CustPhoneNumber = c.CustPhoneNumber,
                            CustType = c.CustType,
                            Createby = c.Createby,
                            Modified = c.Modified,
                            CreateDate = c.CreateDate,
                            ModifiedDate = c.ModifiedDate, CustCode = c.CustCode,
                            #endregion
                        };

            return new PagedList<Customer>(query, pageIndex, pageSize);
        }
        public PagedList<Customer> GetAllCustomer(CustomerSearchResult filter, int pageSize = int.MaxValue, int pageIndex = 0)
        {
            this.SaveCustomerFilter(filter);
            var query = from c in m_context.Customers
                        join t in m_context.CutomerTypes on c.CustType equals t.CutomerTypeId into TypeJoin
                        from t2 in TypeJoin.DefaultIfEmpty()
                        where c.IsActive == true && (c.CustType == filter.CutomerTypeId || filter.CutomerTypeId == 0)
                        orderby c.CustomerId descending
                        select new Customer
                        {
                            CustomerId = c.CustomerId,
                            CustName = c.CustName,
                            CustAddress = c.CustAddress?? c.CustAddress,
                            CustContact = c.CustContact?? c.CustContact,
                            CustTaxCode = c.CustTaxCode,
                            CustEmail = c.CustEmail ?? c.CustEmail,
                            CustMobile = c.CustMobile ?? c.CustMobile,
                            CustPhoneNumber = c.CustPhoneNumber ?? c.CustPhoneNumber,
                            CustType = c.CustType,
                            Createby = c.Createby,
                            Modified = c.Modified,
                            CreateDate = c.CreateDate,
                            ModifiedDate = c.ModifiedDate, CustCode  = c.CustCode,
                            CustTypeName = t2.CutomerTypeName ?? "N/A"
                        };
           
            if (!CommonHelper.IsBlank(filter.CustName))
            {
                query = query.Where(c => c.CustName.ToLower().Contains(filter.CustName.ToLower()));
            }
            if (!CommonHelper.IsBlank(filter.CustEmail))
            {
                query = query.Where(c => c.CustEmail.ToLower().Contains(filter.CustEmail.ToLower()));
            }
            if (!CommonHelper.IsBlank(filter.TaxCode))
            {
                query = query.Where(c => c.CustTaxCode.ToLower().Contains(filter.TaxCode.ToLower()));
            }
            if (!CommonHelper.IsBlank(filter.CustMobile))
            {
                query = query.Where(c => c.CustMobile.ToLower().Contains(filter.CustMobile.ToLower()));
            }
            return new PagedList<Customer>(query, pageIndex, pageSize);
        }
        public Customer GetCustomerById(int customerId)
        {
            var query = from c in m_context.Customers
                        where c.CustomerId == customerId && c.IsActive==true
                        select new Customer
                                            {
                                                #region
                                                CustomerId = c.CustomerId,
                                                CustName = c.CustName,
                                                CustAddress = c.CustAddress,
                                                CustContact = c.CustContact,
                                                CustTaxCode = c.CustTaxCode,
                                                CustEmail = c.CustEmail,
                                                CustMobile = c.CustMobile,
                                                CustPhoneNumber = c.CustPhoneNumber,
                                                CustType = c.CustType,
                                                Createby = c.Createby,
                                                Modified = c.Modified,
                                                CreateDate = c.CreateDate,
                                                ModifiedDate = c.ModifiedDate
                                                #endregion
                                            };
            return query.FirstOrDefault();
        }
        public Customer GetCustomerByName(string name = "")
        {
            var query = from c in m_context.Customers
                        where c.CustName.ToUpper() == name.ToUpper()
                        select new Customer
                        {
                            #region
                            CustomerId = c.CustomerId,
                            CustName = c.CustName,
                            CustAddress = c.CustAddress ?? "",
                            CustContact=c.CustContact ?? "",
                            CustTaxCode=c.CustTaxCode ??"",
                            CustEmail = c.CustEmail ?? "",
                            CustMobile = c.CustMobile ?? "",
                            CustPhoneNumber= c.CustPhoneNumber ?? "",
                            CustType= c.CustType ,
                            Createby = c.Createby,
                            Modified = c.Modified ,
                            CreateDate = c.CreateDate ,
                            ModifiedDate = c.ModifiedDate, CustCode = c.CustCode,
                            #endregion
                        };
            return query.FirstOrDefault();
        }
        #endregion
        public Payroll.BusinessLogic.Data.Object GetNameObject(int id)
        {
            var query = from o in m_context.Objects
                        where o.ObjectId == id 
                        select new Payroll.BusinessLogic.Data.Object
                        {
                            ObjectId = o.ObjectId,
                            ObjectName = o.ObjectName,
                            ObjectTypeId = o.ObjectTypeId
                        };
            return query.FirstOrDefault();
        }
        private void UpdateCustomerLastId(int customerTypeId)
        {
            var item = (from c in m_context.CutomerTypes
                        where c.CutomerTypeId == customerTypeId
                        orderby c.LastId descending
                        select c).FirstOrDefault();
            if (!CommonHelper.IsNull(item))
            {
                item.LastId = item.LastId + 1;
                m_context.SubmitChanges();
            }
        }

        public List<CutomerType> GetCustomerType(string customerType = "")
        {
            if (string.IsNullOrEmpty(customerType))
                customerType = null;
            var query = from c in m_context.CutomerTypes
                        where c.delete == true && (c.CutomerTypeName.Contains(customerType) || customerType == null)
                        orderby c.pre ascending
                        select new CutomerType { 
                            CutomerTypeId = c.CutomerTypeId,
                            CutomerTypeName = c.CutomerTypeName,
                            LastId = c.LastId, 
                            pre = c.pre };
            return query.ToList();
        }
        public CutomerType GetCustomerTypeByid(int id)
        {
            var query = from c in m_context.CutomerTypes
                        where  c.CutomerTypeId==id
                        select new CutomerType
                        {
                            CutomerTypeId = c.CutomerTypeId,
                            CutomerTypeName = c.CutomerTypeName,
                            LastId = c.LastId,
                            pre = c.pre
                        };
            return query.FirstOrDefault();
        }

        public CutomerType SaveCutomerType(CutomerType c)
        {
            var item = (from ct in m_context.CutomerTypes
                        where ct.CutomerTypeId == c.CutomerTypeId
                        select ct).FirstOrDefault();
            if (CommonHelper.IsNull(item))
            {
                m_context.CutomerTypes.InsertOnSubmit(new Payroll.BusinessLogic.Data.CutomerType { CutomerTypeName = c.CutomerTypeName, LastId = 0, pre = c.pre, delete = true });
                m_context.SubmitChanges();
            }
            return c;
        }

        public int DelateCutomerType(int cutomerTypeId)
        {
            var item = (from ct in m_context.CutomerTypes
                        where ct.CutomerTypeId == cutomerTypeId
                        select ct).FirstOrDefault();
            if (!CommonHelper.IsNull(item))
            {
                item.delete = false;
                m_context.SubmitChanges();
            }
            return 1;
        }
        #region image

        private string SavePictureInFile(string pictureId, byte[] pictureBinary, string mimeType, string ImagePath)
        {
            string[] parts = mimeType.Split('/');
            string lastPart = parts[parts.Length - 1];
            switch (lastPart)
            {
                case "pjpeg":
                    lastPart = "jpg";
                    break;
                case "x-png":
                    lastPart = "png";
                    break;
                case "x-icon":
                    lastPart = "ico";
                    break;
            }
            string localFilename = string.Format("{0}_0.{1}", pictureId, lastPart);
            this.DeletePictureByPictureId(pictureId, ImagePath);
            SavePictureToImage(Path.Combine(ImagePath, localFilename), pictureBinary, this.LocalPicel, lastPart);

            //File.WriteAllBytes(Path.Combine(LocalImagePath, localFilename), pictureBinary);

            return CommonHelper.GetStoreLocation() + "images/Customer/" + localFilename; ;
        }
        private void SavePictureToImage(string localFilename, byte[] pictureBinary, int targetSize, string lastPart)
        {
            using (MemoryStream stream = new MemoryStream(pictureBinary))
            {
                var b = new Bitmap(stream);

                var newSize = CalculateDimensions(b.Size, targetSize);

                if (newSize.Width < 1)
                    newSize.Width = 1;
                if (newSize.Height < 1)
                    newSize.Height = 1;

                var newBitMap = new Bitmap(newSize.Width, newSize.Height);
                var g = Graphics.FromImage(newBitMap);
                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
                g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
                g.DrawImage(b, 0, 0, newSize.Width, newSize.Height);
                var ep = new EncoderParameters();
                ep.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, this.ImageQuality);
                ImageCodecInfo ici = GetImageCodecInfoFromExtension(lastPart);
                if (ici == null)
                    ici = GetImageCodecInfoFromMimeType("image/jpeg");
                newBitMap.Save(localFilename, ici, ep);
                newBitMap.Dispose();
                b.Dispose();
            }
        }
        public void DeletePictureByPictureId(string pictureId, string Local)
        {
            //delete thumbs
            string filter = string.Format("{0}*.*", pictureId);
            string[] currentFiles = System.IO.Directory.GetFiles(Local, filter);
            foreach (string currentFileName in currentFiles)
                File.Delete(Path.Combine(Local, currentFileName));


        }
        public void DeletePicture(string pictureId, string MimeType)
        {
            //delete thumbs
            string filter = string.Format("{0}*.*", pictureId);
            string[] currentFiles = System.IO.Directory.GetFiles(this.LocalThumbImagePath, filter);
            foreach (string currentFileName in currentFiles)
                File.Delete(Path.Combine(this.LocalThumbImagePath, currentFileName));

            //delete from file system
            DeletePictureOnFileSystem(pictureId, MimeType);
        }
        private void DeletePictureOnFileSystem(string pictureId, string MimeType)
        {
            if (MimeType == null)
                throw new ArgumentNullException("picture");

            string[] parts = MimeType.Split('/');
            string lastPart = parts[parts.Length - 1];
            switch (lastPart)
            {
                case "pjpeg":
                    lastPart = "jpg";
                    break;
                case "x-png":
                    lastPart = "png";
                    break;
                case "x-icon":
                    lastPart = "ico";
                    break;
            }
            string localFilename = string.Format("{0}_0.{1}", pictureId, lastPart);
            string localFilepath = Path.Combine(LocalImagePath, localFilename);
            if (File.Exists(localFilepath))
            {
                File.Delete(localFilepath);
            }
        }
        /// <summary>
        /// Calculates picture dimensions whilst maintaining aspect
        /// </summary>
        /// <param name="originalSize">The original picture size</param>
        /// <param name="targetSize">The target picture size (longest side)</param>
        /// <returns></returns>
        private Size CalculateDimensions(Size originalSize, int targetSize)
        {
            var newSize = new Size();
            if (originalSize.Height > originalSize.Width) // portrait 
            {
                newSize.Width = (int)(originalSize.Width * (float)(targetSize / (float)originalSize.Height));
                newSize.Height = targetSize;
            }
            else // landscape or square
            {
                newSize.Height = (int)(originalSize.Height * (float)(targetSize / (float)originalSize.Width));
                newSize.Width = targetSize;
            }
            return newSize;
        }
        /// <summary>
        /// Loads a cpiture from file
        /// </summary>
        /// <param name="pictureId">Picture identifier</param>
        /// <param name="mimeType">MIME type</param>
        /// <returns>Picture binary</returns>
        public byte[] LoadPictureFromFile(string pictureId, string mimeType)
        {
            string[] parts = mimeType.Split('/');
            string lastPart = parts[parts.Length - 1];
            switch (lastPart)
            {
                case "pjpeg":
                    lastPart = "jpg";
                    break;
                case "x-png":
                    lastPart = "png";
                    break;
                case "x-icon":
                    lastPart = "ico";
                    break;
            }
            string localFilename = string.Empty;
            localFilename = string.Format("{0}_0.{1}", pictureId, lastPart);
            if (!File.Exists(Path.Combine(LocalImagePath, localFilename)))
            {
                return new byte[0];
            }
            return File.ReadAllBytes(Path.Combine(LocalImagePath, localFilename));
        }
        /// <summary>
        /// Returns the first ImageCodecInfo instance with the specified mime type.
        /// </summary>
        /// <param name="mimeType">Mime type</param>
        /// <returns>ImageCodecInfo</returns>
        private ImageCodecInfo GetImageCodecInfoFromMimeType(string mimeType)
        {
            var info = ImageCodecInfo.GetImageEncoders();
            foreach (var ici in info)
                if (ici.MimeType.Equals(mimeType, StringComparison.OrdinalIgnoreCase))
                    return ici;
            return null;
        }
        /// <summary>
        /// Returns the first ImageCodecInfo instance with the specified extension.
        /// </summary>
        /// <param name="fileExt">File extension</param>
        /// <returns>ImageCodecInfo</returns>
        private ImageCodecInfo GetImageCodecInfoFromExtension(string fileExt)
        {
            fileExt = fileExt.TrimStart(".".ToCharArray()).ToLower().Trim();
            switch (fileExt)
            {
                case "jpg":
                case "jpeg":
                    return GetImageCodecInfoFromMimeType("image/jpeg");
                case "png":
                    return GetImageCodecInfoFromMimeType("image/png");
                case "gif":
                    //use png codec for gif to preserve transparency
                    //return GetImageCodecInfoFromMimeType("image/gif");
                    return GetImageCodecInfoFromMimeType("image/png");
                default:
                    return GetImageCodecInfoFromMimeType("image/jpeg");
            }
        }
        #endregion
        #region CustomerFilters
        protected void SaveCustomerFilter(CustomerSearchResult cf)
        {
            var item = (from c in m_context.CustomerFilters
                        where c.UserId == cf.UserId
                        select c).FirstOrDefault();

            if (CommonHelper.IsNull(item))
            {
                m_context.CustomerFilters.InsertOnSubmit(new CustomerFilter
                {
                    UserId = cf.UserId,
                    CustName = cf.CustName,
                    CustMobile = cf.CustMobile,
                    CutomerTypeId = cf.CutomerTypeId,
                    CustEmail = cf.CustEmail,
                    CustTaxCode = cf.TaxCode
                });
            }
            else
            {
                item.UserId = cf.UserId;
                item.CustName = cf.CustName;
                item.CustMobile = cf.CustMobile;
                item.CutomerTypeId = cf.CutomerTypeId;
                item.CustEmail = cf.CustEmail;
                item.CustTaxCode = cf.TaxCode;
            }
            m_context.SubmitChanges();
        }
        #endregion
        public CustomerSearchResult GetCustomerSearch(int UserId)
        {
            var query = from c in m_context.CustomerFilters
                        where c.UserId == UserId
                        select new CustomerSearchResult
                        {
                            UserId = c.UserId,
                            CustName = c.CustName,
                            CustMobile = c.CustMobile,
                            TaxCode = c.CustTaxCode,
                            CutomerTypeId = c.CutomerTypeId.Value,
                            CustEmail = c.CustEmail
                        };
            return query.FirstOrDefault();
        }
    }
}
